docs(permissions): generate system-context.mdx's declared counts instead of hand-typing them - #17043
Merged
Merged
Conversation
…hand-typing them `check-system-context-census.mjs --fix` regenerates every DECLARED_COUNTS sentence (the headline, the decomposition table, the plugin-sharing share, the ruling quote) straight from a fresh census, reusing the exact pattern/value pair the check already runs -- as a write instead of a comparison. Anchors are unaffected: they still have nothing mechanical to repair (symbol anchors encode no position), so `--fix` refuses loudly on a sentence it can no longer parse rather than writing a partial page. This removes the failure class rather than detecting it one gate at a time: two branches independently (and correctly, for their own tree) bumping the same sentence to the same number text-merge clean with no conflict, and the merged total is neither side's -- which is the failure mode this change responds to. The fix is to stop hand-retyping the number at all. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zTkyNHJ7TkuN2oXtP5x37
…nerate-system-context-counts
os-trump
marked this pull request as ready for review
September 9, 2026 04:43
os-trump
enabled auto-merge
September 9, 2026 04:43
os-trump
deleted the
claude/issue-16919-generate-system-context-counts
branch
September 9, 2026 05:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #16919
What changed
check-system-context-census.mjs --fix(aliasedpnpm gen:system-context-census) now regenerates everyDECLARED_COUNTSsentence incontent/docs/permissions/system-context.mdxfrom a fresh census, instead of only comparing them. It reuses the exactpattern/valuepair the COUNTS check already runs — as a write instead of a comparison — so there is exactly one definition of what each number means, read twice. Anchors are untouched: they still have nothing mechanical to repair (symbol anchors encode no position), and--fixrefuses loudly, writing nothing, if a sentence no longer parses.This is direction 1 from #16919, as dispatched: the seven-plus hand-typed count sentences become generated output instead of a human re-deriving and re-typing a number after every CI red.
scripts/check-system-context-census.mjs— newregenerateDeclaredCounts()(pure: text in, text + rewrites + errors out), wired into--fix;reportNoFixnarrowed toreportNoAnchorFixsince counts are no longer in that "nothing to rewrite" bucket; self-test battery renamed and extended (2 → 8 cases) to pin the new write behavior and that anchors still don't get one.scripts/regen-artifacts.mjs— thesystem-context.mdxrow's comment corrected: it used to assert--fixrefuses on any declared-count mismatch; it now regenerates them.content/docs/permissions/system-context.mdx— one paragraph in "Maintaining this table" documenting the new generator and telling the next author never to hand-retype a digit.Why (the guarantee this buys)
The failure #16919 was filed over is silent at every layer that could see it: the merge driver resolves text, and two branches independently (and correctly, for their own tree) writing the same digit into the same sentence merge clean with no conflict — the merged total is neither side's number. Only an independent recomputation (the COUNTS check) ever saw it, and until now the repair was "a human re-derives the number and retypes it," which is the same manual-arithmetic step that produced the original defect.
After this change the repair is
pnpm gen:system-context-census, on the tree you actually want counted — mechanical, and it refuses rather than writing a partial page if the wording it reads has moved. It also makes the next hand-edit of one of these sentences loud rather than silent going forward: PR #16860 (open, unrelated) still hand-corrects these same seven sentences to a literal digit on its own branch; when the two branches meet, git now sees a real edit to the sentence structure on one side and a bare digit bump on the other, which is a genuine conflict — not the "both sides typed the same digit" shape that produced this card. That said, I'm not claiming the deeper property that two generator runs against different trees can never coincidentally produce identical text — they still can, for the same reason two independent correct arithmetic results can agree. What's removed is the hand-typing step, which is the actual defect this card names.--fixstill cannot add or drop a table row — a site that arrived or vanished is a human's editorial call, same as before; it only keeps the aggregate counts in lockstep with whatever rows exist.The counter is live — reading recorded, not re-bumped
Per the dispatch's warning, I checked whether
origin/mainmoved the true count while this branch was open:555a89cbd):check-system-context-census: OK — 107 elevation read sites in 20 packages across 45 files...origin/maintip at time of the check (2e8e1185b, in a disposable worktree, no shared state with this branch): same reading, 107 sites, andgit diffbetween the two commits touches none ofcontent/docs/permissions/system-context.mdx,scripts/check-system-context-census.mjs, orscripts/regen-artifacts.mjs.origin/maininto this branch (clean merge, no conflicts — touched files:packages/lint,packages/objectql,packages/rest,packages/spec/scripts/liveness, two changesets; none overlapping this PR's files): re-ran both--self-testand the plain check on head3139e826a— still 107, exit 0.So the counter did not move during this round; nothing was re-bumped.
Verification
Ablation — predicted before running, then measured
Predicted: mutating the headline sentence's
107to999on disk makes the gate refuse, naming the census's real value; restoring returns the file to its exact original bytes.Restored under
trap '... git checkout HEAD -- "$ABS"' EXIT INT TERM. Restoration proof, not exit-code proof:Idempotence, on the same mutation
Predicted: one
--fixrun repairs the999back to107exactly (byte-identical to the pre-mutation original); a second--fixrun is then a true no-op with the same hash.HASH1 == HASH2(idempotent) andHASH1 == HEAD_BLOB(the regenerated sentence is byte-for-byte the original, not merely "a passing value"). Restored again under the same trap; finalgit status/git diff HEADclean.Generated, not edited
Both the ablation and idempotence runs above mutated and repaired the file exclusively through
sed/the script's ownwriteFileSync, never through an editor; the one hand-authored change to this doc in this PR is the new documentation paragraph, made with the file freshly re-read after the ablation script'straprestore overwrote my first attempt at it (caught by re-grepping for the paragraph before proceeding — worth naming since it's exactly the kind of silent loss this card is about, just at the tooling layer instead of the merge layer).Self-test and check, before and after the
origin/mainmergeGate reconciliation
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackagainst merge-base2e8e1185boforigin/mainand this branch's HEAD (3139e826a) derived 63 commands (36 pnpm, 27 direct node).@objectstack/lint,@objectstack/client-react/@objectstack/clientnot built —check:doc-formula-expressions,check:doc-security-posture,check:docs-transcript-driftall exit 3 "PREREQUISITE NOT MET",check:skill-examplesexit 1 with the same "package is not built" refusal, own dist caveat). None reported as a pass on that first answer.pnpm --filter '@objectstack/lint...' buildandpnpm --filter '@objectstack/client-react...' build, re-ran all four → exit 0 on all four (check:skill-examples→ "258 prose examples type-check across 3 surface(s)";check:docs-transcript-drift→ "4 declared transcript value(s) across 403 page(s) ... equal what the registry derives today").check:route-envelopeis in the deriver's Silent bucket (dispatch-gates: a whole-tree-walk gate whose workflownames:lists only its CURRENT members is placed Silent, so it is never derived for the card that adds a new member — measured on check:route-envelope / PR #16730 #16828) and is never derived — run explicitly per the dispatch note: exit 0, "0 ratcheted" everywhere, no new response-writing module (this diff adds none).check:system-context-census— the gate this card is about — is in the derived 63 and was also run explicitly and repeatedly above: exit 0 throughout.check:pm-widening-tells:node scripts/pm/check-widening-tells.mjs --declaration no --diff PR.DIFF(this PR's own diff) →✓ 3 changed file(s) read, no widening tell on any declared surface.check:pm-governed-merges --teston the final 3-path file list →0 of 3 path(s) hit the register (5 surfaces) ... NOT governed.Clause-② stays
noas declared at claim time: no new exported symbol, no new key on a published payload, nopackages/spec/src/**path.Direction 2 — sweep for other hand-maintained totals (measurement, not a second fix)
Swept
content/docs/**/*.mdx(181 hand-written pages, excluding the auto-generatedreferences/tree and the release-ownedreleases/tree) for a bold or bare integer sitting next to a countable-population noun (sites/packages/files/routes/tests/checks/rows/...), then checked whether anyscripts/**/*.mjsreferences that doc's path literally (the same relationshipcheck-system-context-census.mjshas with its own page).⭐ Positive control: FIRED. The sweep re-found
content/docs/permissions/system-context.mdxitself (4 hits), correctly marked COVERED (scripts/check-system-context-census.mjs,scripts/isystem-census.mjs,scripts/regen-artifacts.mjs, …). Since the detector can re-find the one instance we know exists, its answer about the rest of the corpus is a real reading, not aNOT MEASUREDzero.api/error-catalog.mdxapi/plugin-endpoints.mdx**404**HTTP status, not a population totalautomation/approvals.mdx**403**HTTP status, not a population totalautomation/flows.mdx**403**HTTP status near "route", gated incidentallypermissions/system-context.mdxpermissions/tenant-audit-census.mdxprotocol/backward-compatibility.mdx.changeset/config.json'sfixedgroup and the actual non-privatepackages/**/package.jsoncount both measure 70 today. Filed as #17039protocol/kernel/error-handling.mdxprotocol/objectui/concept.mdxAnswer to the card's question: on this sweep,
system-context.mdxis not the lucky one — it's one of at least two. The other files that matched are either already covered by a gate (mostly HTTP status codes sitting near a word the regex read as a population noun) or genuinely stale (backward-compatibility.mdx, filed). Not widened into this PR per the dispatch — filed separately, reported below.This heuristic is a text-shape sweep, not an AST census: it does not claim completeness over every possible phrasing of a hand-maintained total, only over the "bold/bare integer beside a population noun" shape it was built to catch — the same shape this card's own incident had.
Changeset
skip-changeset(label applied on this PR). Nothing published: the diff touchesscripts/**(root dev tooling, not part of any published package'ssrc) andcontent/docs/permissions/**(a docs page, not an npm-published artifact). Percheck-empty-changeset.mjs's own header — "this PR edits a CI-internal script... is the textbookskip-changesetcase — such a PR releases nothing" — and an empty-frontmatter changeset is mechanically rejected by that gate when newly added, so a changeset file isn't the right carrier here either way. The load-bearing guarantee (generation over hand-typing, and what that does and doesn't buy against future merges) is stated above instead.Out-of-scope findings
content/docs/protocol/backward-compatibility.mdxstates "69 packages" in the lockstep group three times; the actual count (both.changeset/config.json'sfixedarray and non-privatepackages/**/package.json) is 70 today. Same shape of defect as this card (hand-maintained repo-population total, no gate recomputes it), unrelated file, no dependency on this PR's diff — filed rather than folded in.🤖 Generated with Claude Code
https://claude.ai/code/session_012zTkyNHJ7TkuN2oXtP5x37
Generated by Claude Code